package cn.quang.search.admin.service.impl;

import cn.quang.search.admin.entity.dto.Operator;
import cn.quang.search.admin.entity.dto.Result;
import cn.quang.search.admin.entity.po.*;
import cn.quang.search.admin.entity.vo.condition.SearchConditionRequest;
import cn.quang.search.admin.mapper.*;
import cn.quang.search.admin.service.ISearchConditionService;
import cn.quang.search.admin.service.common.RedisService;
import cn.quang.search.admin.utils.AssertUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author:  Entity Generator
 * @since:  2024-02-28 10:58:35
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SearchConditionService implements ISearchConditionService {

	private final SearchConditionMapper searchConditionMapper;
	private final SearchConditionTableRelationMapper searchConditionTableRelationMapper;
	private final EntityLogicTableMapper entityLogicTableMapper;
	private final SearchSceneMapper searchSceneMapper;
	private final SearchSceneConfigMapper searchSceneConfigMapper;
	private final SearchScenePresetConditionConfigMapper searchScenePresetConditionConfigMapper;
	
	private final SearchConfigChangeService searchConfigChangeService;
	private final RedisService redisService;
	private static final String LOCK_KEY = "CRM3$SEARCH_CONDITION$";
	private static final int EXPIRE_SECONDS = 60;

	/**
	 * 添加条件解析器
	 * @param operator 操作人
	 * @param request 请求参数
	 */
	@Override
	public Result<Long> add(Operator operator, SearchConditionRequest request){
		Result<Long> methodResult = new Result<>();
		AssertUtils.argumentBlank(request.getDic(), "必须提供查询条件标识");
		AssertUtils.argumentBlank(request.getName(), "必须提供查询条件名称");
		List<SearchConditionRequest.LogicTableRequest> logicTables = request.getLogicTables();
		AssertUtils.argumentCollectionEmpty(logicTables, "必须提供查询条件关联的逻辑表");

		String dic = request.getDic();
		String uniqueKey = LOCK_KEY + dic;
		String requestId = UUID.randomUUID().toString();
		Result<?> checkResult = checkDicLogicTableRelations(0, dic, logicTables);
		if(checkResult.isFail()){
			return methodResult.changeErr(checkResult.getMessage());
		}

		if(redisService.tryLock(uniqueKey, requestId, EXPIRE_SECONDS)){
			try {
				// 新增condition
				SearchCondition condition = new SearchCondition();
				condition.setDic(request.getDic());
				condition.setName(request.getName());
				condition.setDescription(request.getDescription());
				condition.setConditionScfServiceName(request.getConditionScfServiceName());
				condition.setConditionScfServiceUrl(request.getConditionScfServiceUrl());
				condition.setIgnoreValues(request.getIgnoreValues());
				condition.setAsyncBoost(request.isAsyncBoost());
				Date now = new Date();
				condition.setCreatorId(operator.getOperatorId());
				condition.setCreateTime(now);
				condition.setModifierId(operator.getOperatorId());
				condition.setModifyTime(now);
				long conditionId = searchConditionMapper.insert(condition);

				for (SearchConditionRequest.LogicTableRequest logicTable : logicTables) {
					// 校验在系统内是否存在
					List<SearchCondition> existSearchConditions = searchConditionMapper.selectByDic(dic);
					if(CollectionUtils.isNotEmpty(existSearchConditions)){
						List<Long> conditionIds = existSearchConditions.stream().map(SearchCondition::getId).collect(Collectors.toList());
						List<SearchConditionTableRelation> tableRelations = searchConditionTableRelationMapper.selectByConditionIds(conditionIds);
						if(CollectionUtils.isNotEmpty(tableRelations)){
							SearchConditionTableRelation tableRelation = tableRelations.stream().filter(relation -> relation.getLogicTableId() == logicTable.getLogicTableId()).findAny().orElse(null);
							if(tableRelation != null){
								return methodResult.changeErr(String.format("系统内已存在该条件和逻辑表的对应关系(conditionId=%s)", tableRelation.getConditionId()));
							}
						}
					}

					// 执行表关系添加
					SearchConditionTableRelation relation = new SearchConditionTableRelation();
					relation.setLogicTableId(logicTable.getLogicTableId());
					relation.setConditionId(conditionId);
					relation.setCreatorId(operator.getOperatorId());
					relation.setCreateTime(now);
					relation.setModifierId(operator.getOperatorId());
					relation.setModifyTime(now);
					searchConditionTableRelationMapper.insert(relation);
				}
			} catch (Exception e){
				log.error("添加查询条件失败", e);
				return methodResult.changeErr("查询条件添加失败，系统异常：" + e.getMessage());
			} finally {
				redisService.releaseLock(uniqueKey, requestId);
			}
		}
		return methodResult;
	}

	/**
	 * 校验系统内是否存在条件和逻辑表的对应关系
	 * @param dic 条件Key
	 * @param logicTableIds 逻辑表IDs
	 */
	private Result<?> checkDicLogicTableRelations(long conditionId, String dic, List<SearchConditionRequest.LogicTableRequest> logicTableIds) {
		Result<?> aopResult = new Result<>();
		try {
			for (SearchConditionRequest.LogicTableRequest logicTableRequest : logicTableIds) {
				// 校验在系统内是否存在
				List<SearchCondition> existSearchConditions = searchConditionMapper.selectByDic(dic);
				if (CollectionUtils.isNotEmpty(existSearchConditions)) {
					List<Long> conditionIds = existSearchConditions.stream().map(SearchCondition::getId).collect(Collectors.toList());
					List<SearchConditionTableRelation> tableRelations = searchConditionTableRelationMapper.selectByConditionIds(conditionIds);
					if (CollectionUtils.isNotEmpty(tableRelations)) {
						for (SearchConditionTableRelation tableRelation : tableRelations) {
							if(tableRelation.getLogicTableId() == logicTableRequest.getLogicTableId() && tableRelation.getConditionId() != conditionId) {
								return aopResult.changeErr(String.format("已存在条件(%s)且已与逻辑表(%s)关联，不能重复添加！", dic, logicTableRequest.getLogicTableName()));
							}
						}
					}
				}
			}
		} catch (Exception e) {
			log.error(String.format("校验查询条件是否重复出现异常(dic=%s, conditionId=%s)", dic, conditionId), e);
			return aopResult.changeErr("无法校验查询条件配置是否重复，请稍后重试！");
		}
		return aopResult;
	}

	/**
	 * 更新查询条件
	 * @param operator 操作人
	 * @param conditionId 条件ID
	 * @param request 更新请求
	 */
	@Override
	public Result<?> update(Operator operator, long conditionId, SearchConditionRequest request){
		Result<?> aopResult = new Result<>();

		// 存储增删改的逻辑表名称，用于输出日志
		List<String> newLogicTableNames = Lists.newArrayList();
		List<String> modifyLogicTableNames = Lists.newArrayList();
		List<String> deleteLogicTableNames = Lists.newArrayList();

		SearchCondition searchCondition = searchConditionMapper.selectById(conditionId);
		AssertUtils.argumentNull(searchCondition, "系统内不存在该查询条件，无法更新");

		List<SearchConditionRequest.LogicTableRequest> logicTables = request.getLogicTables();
		if(CollectionUtils.isEmpty(logicTables)){
			logicTables = Lists.newArrayList();
		}

		Result<?> checkResult = checkDicLogicTableRelations(conditionId, StringUtils.isBlank(request.getDic()) ? searchCondition.getDic() : request.getDic(), logicTables);
		if(checkResult.isFail()){
			return aopResult.changeErr(checkResult.getMessage());
		}

		String dic = StringUtils.isNotBlank(request.getDic()) ? request.getDic() : searchCondition.getDic();
		String uniqueKey = LOCK_KEY + dic;
		String requestId = UUID.randomUUID().toString();
		if(redisService.tryLock(uniqueKey, requestId, EXPIRE_SECONDS)){
			try {
				Date now = new Date();
				searchCondition.setDic(request.getDic());
				searchCondition.setName(request.getName());
				searchCondition.setDescription(request.getDescription());
				searchCondition.setConditionScfServiceName(request.getConditionScfServiceName());
				searchCondition.setConditionScfServiceUrl(request.getConditionScfServiceUrl());
				searchCondition.setIgnoreValues(request.getIgnoreValues());
				searchCondition.setAsyncBoost(request.isAsyncBoost());
				searchCondition.setModifierId(operator.getOperatorId());
				searchCondition.setModifyTime(now);

				searchConditionMapper.updateById(searchCondition);
				// 同时，更新对应关系
				List<SearchConditionTableRelation> relations = searchConditionTableRelationMapper.selectByConditionId(conditionId);
				if(relations == null) { relations = Lists.newArrayList(); }
				Map<Long, SearchConditionTableRelation> conditionTableRelationMap = relations.stream().collect(Collectors.toMap(SearchConditionTableRelation::getLogicTableId, v -> v));
				Map<Long, SearchConditionRequest.LogicTableRequest> conditionTableRequestMap = logicTables.stream().collect(Collectors.toMap(SearchConditionRequest.LogicTableRequest::getLogicTableId, v -> v));

				// 执行删除(解除条件和逻辑表的关联关系，需要校验是否存在某个场景基于该逻辑表关联了该查询条件，如果存在，则应该先解除场景下的关联关系)
				List<Long> deleteRelationIds = Lists.newArrayList();
				for (SearchConditionTableRelation relation : relations) {
					long logicTableId = relation.getLogicTableId();
					if(!conditionTableRequestMap.containsKey(logicTableId)){
						EntityLogicTable logicTable = entityLogicTableMapper.selectById(relation.getLogicTableId());
						List<SearchSceneConfig> searchScenes = searchSceneConfigMapper.selectByLogicTableId(logicTableId);
						List<SearchSceneConfig> searchConditions = searchSceneConfigMapper.selectByConditionId(conditionId);
						if(CollectionUtils.isNotEmpty(searchScenes) && CollectionUtils.isNotEmpty(searchConditions)) {
							Set<Long> sceneIds = searchConditions.stream().map(SearchSceneConfig::getSceneId).collect(Collectors.toSet());
							for (SearchSceneConfig searchScene : searchScenes) {
								if(sceneIds.contains(searchScene.getSceneId())) {
									SearchScene scene = searchSceneMapper.selectById(searchScene.getSceneId());
									return aopResult.changeErr(String.format("查询场景(%s)基于逻辑表(%s)关联了该查询条件，必须先解除场景上的关联后，方可在查询条件上解绑该逻辑表", String.format("%s(%s)", scene.getCode(), scene.getName()), logicTable.getName()));
								}
							}
						}
						// 删除
						deleteRelationIds.add(relation.getId());
						deleteLogicTableNames.add(logicTable == null ? "未知" : logicTable.getName());
					}
				}
				for (Long deleteRelationId : deleteRelationIds) { searchConditionTableRelationMapper.deleteById(deleteRelationId); }

				// 比较更新 ： 存在的更新，不存在的新增，未出现在请求中的删除
				for (SearchConditionRequest.LogicTableRequest logicTableRequest : logicTables) {
					SearchConditionTableRelation relation = conditionTableRelationMap.get(logicTableRequest.getLogicTableId());
					if(relation != null){
						// 已存在的关联关系，执行更新
						relation.setModifierId(operator.getOperatorId());
						relation.setModifyTime(now);
						searchConditionTableRelationMapper.updateById(relation);
						modifyLogicTableNames.add(logicTableRequest.getLogicTableName());
					} else {
						// 新增
						relation = new SearchConditionTableRelation();
						relation.setConditionId(conditionId);
						relation.setLogicTableId(logicTableRequest.getLogicTableId());
						relation.setCreatorId(operator.getOperatorId());
						relation.setCreateTime(now);
						relation.setModifierId(operator.getOperatorId());
						relation.setModifyTime(now);
						searchConditionTableRelationMapper.insert(relation);
						newLogicTableNames.add(logicTableRequest.getLogicTableName());
					}
				}
				searchConfigChangeService.triggerByCondition(conditionId);
			} catch (Exception e) {
				log.error(String.format("查询条件(%s)变更失败", conditionId), e);
				return aopResult.changeErr("查询条件更新失败: " + e.getMessage());
			} finally {
				redisService.releaseLock(uniqueKey, requestId);
			}
		}

		log.info(String.format("逻辑表关联真实表：新增表%s，修改表%s，删除表%s", newLogicTableNames, modifyLogicTableNames, deleteLogicTableNames));
		return aopResult;
	}

	/**
	 * 删除查询条件
	 * @param operator 操作人
	 * @param conditionId 条件ID
	 * @return 删除结果
	 */
	@Override
	public Result<?> delete(Operator operator, long conditionId){
		Result<?> aopResult = new Result<>();
		try {
			SearchCondition searchCondition = searchConditionMapper.selectById(conditionId);
			if(searchCondition == null) {
				return aopResult.changeErr("系统内已不存在该查询条件");
			}

			List<SearchConditionTableRelation> searchConditionTableRelations = searchConditionTableRelationMapper.selectByConditionId(conditionId);
			if(CollectionUtils.isNotEmpty(searchConditionTableRelations)){
				List<Long> logicTableIds = searchConditionTableRelations.stream().map(SearchConditionTableRelation::getLogicTableId).distinct().collect(Collectors.toList());
				List<EntityLogicTable> logicTables = entityLogicTableMapper.selectList(new QueryWrapper<EntityLogicTable>().lambda().in(EntityLogicTable::getId, logicTableIds));
				return aopResult.changeErr("存在关联的逻辑表：" + logicTables.stream().map(EntityLogicTable::getName).collect(Collectors.joining(", ")));
			}

			// 检查是否存在查询条件关联的查询场景
			List<SearchSceneConfig> sceneConfigs = searchSceneConfigMapper.selectByConditionId(conditionId);
			if(CollectionUtils.isNotEmpty(sceneConfigs)){
				List<Long> sceneIds = sceneConfigs.stream().map(SearchSceneConfig::getSceneId).distinct().collect(Collectors.toList());
				List<SearchScene> scenes = searchSceneMapper.selectList(new QueryWrapper<SearchScene>().lambda().in(SearchScene::getId, sceneIds));
				return aopResult.changeErr("存在关联的查询场景：" + scenes.stream().map(input -> String.format("%s(%s)", input.getCode(), input.getName())).collect(Collectors.joining(", ")));
			}

			// 检查是否存在查询条件关联的预设查询条件
			List<SearchScenePresetConditionConfig> presetConditionConfigs = searchScenePresetConditionConfigMapper.selectByConditionId(conditionId);
			if(CollectionUtils.isNotEmpty(presetConditionConfigs)) {
				List<Long> sceneIds = presetConditionConfigs.stream().map(SearchScenePresetConditionConfig::getFieldDicId).distinct().collect(Collectors.toList());
				List<SearchScene> scenes = searchSceneMapper.selectList(new QueryWrapper<SearchScene>().lambda().in(SearchScene::getId, sceneIds));
				return aopResult.changeErr("查询场景的预设条件中关联了该条件：" + scenes.stream().map(input -> String.format("%s(%s)", input.getCode(), input.getName())).collect(Collectors.joining(", ")));
			}

			searchConditionMapper.deleteById(conditionId);
		} catch (Exception e) {
			log.error(String.format("删除查询条件(%s)出现异常", conditionId), e);
			return aopResult.changeErr("删除查询条件出现系统异常：" + e.getMessage());
		}
		return aopResult;
	}

//	@Override
//	public Result<Pagination<SearchConditionListItemVO>> list4View(Operator operator, SearchConditionQueryRequest request) {
//		Result<Pagination<SearchConditionListItemVO>> aopResult = new Result<>();
//
//		SearchGroup searchGroup = new SearchGroup(SearchLogicType.AND);
//		if(StringUtils.isNotBlank(request.getDic())) {
//			searchGroup.addSearch(SearchCondition.COL_DIC, SearchOperator.Equal, request.getDic());
//		}
//		if(StringUtils.isNotBlank(request.getName())){
//			searchGroup.addSearch(SearchCondition.COL_NAME, SearchOperator.Equal, request.getName());
//		}
//		if(StringUtils.isNotBlank(request.getStartCreateTime())){
//			Date startCreateTime = DateUtil.parse(request.getStartCreateTime(), DateUtil.PATTERN_FULL);
//			searchGroup.addSearch(SearchCondition.COL_CREATE_TIME, SearchOperator.GreaterThanOrEqual, startCreateTime);
//		}
//		if(StringUtils.isNotBlank(request.getEndCreateTime())){
//			Date endCreateTime = DateUtil.parse(request.getEndCreateTime(), DateUtil.PATTERN_FULL);
//			searchGroup.addSearch(SearchCondition.COL_CREATE_TIME, SearchOperator.LessThan, endCreateTime);
//		}
//		try {
//			Pagination<SearchCondition> entitiesPagination = this.searchConditionMapper.findEntitiesPagination(null, searchGroup, request.getPageIndex(), request.getPageSize(), String.format("%s desc", EntityDataSource.COL_CREATE_TIME));
//			Pagination<SearchConditionListItemVO> pagination = new Pagination<>(request.getPageIndex(), request.getPageSize(), entitiesPagination.getTotalCount());
//			if(CollectionUtils.isNotEmpty(entitiesPagination)) {
//				for (SearchCondition searchCondition : entitiesPagination) {
//					pagination.add(convertToListItemVo(searchCondition));
//				}
//			}
//			return aopResult.changeSucc(pagination);
//		} catch (Exception e) {
//			logger.error("逻辑表查询失败", e);
//			return aopResult.changeErr("逻辑表查询失败：" + e.getMessage());
//		}
//	}

//	private SearchConditionListItemVO convertToListItemVo(SearchCondition searchCondition) {
//		SearchConditionListItemVO vo = new SearchConditionListItemVO();
//		vo.setId(searchCondition.getId());
//		vo.setDic(searchCondition.getDic());
//		vo.setName(searchCondition.getName());
//		vo.setDescription(searchCondition.getDescription());
//		vo.setConditionScfServiceName(searchCondition.getConditionScfServiceName());
//		vo.setConditionScfServiceUrl(searchCondition.getConditionScfServiceUrl());
//		vo.setAsyncBoost(searchCondition.getAsyncBoost() == DBConstants.DATA_TRUE ? "是" : "否");
//		vo.setIgnoreValues(searchCondition.getIgnoreValues());
//
//		vo.setCreatorName(BspService.getBspUserNameById(searchCondition.getCreatorId()));
//		vo.setCreateTimeFormat(DateUtil.format(searchCondition.getCreateTime()));
//		vo.setModifierName(BspService.getBspUserNameById(searchCondition.getModifierId()));
//		vo.setModifyTimeFormat(DateUtil.format(searchCondition.getModifyTime()));
//		return vo;
//	}

//	@Override
//	public Result<SearchConditionDetailVO> detail4View(Operator operator, long id) {
//		Result<SearchConditionDetailVO> aopResult = new Result<>();
//		try {
//			SearchCondition entity = searchConditionMapper.findEntityById(id);
//			return aopResult.changeSucc(convertToDetailVo(entity));
//		} catch (Exception e) {
//			logger.error(String.format("逻辑表(%s)查询失败", id), e);
//			return aopResult.changeErr("逻辑表详情查询失败：" + e.getMessage());
//		}
//	}

	/**
	 * 根据逻辑表ID获取所有的关联查询条件
	 * @param operator 操作人
	 * @param logicTableId 逻辑表
	 */
//	@Override
//	public Result<List<SearchConditionListItemVO>> byLogicTableId4View(Operator operator, long logicTableId) {
//		Result<List<SearchConditionListItemVO>> aopResult = new Result<>();
//		try {
//			List<SearchConditionTableRelation> conditionTableRelations = searchConditionTableRelationMapper.selectByLogicTableId(logicTableId);
//			List<SearchConditionListItemVO> vos = Lists.newArrayList();
//			if(CollectionUtils.isNotEmpty(conditionTableRelations)) {
//				List<Long> conditionIds = conditionTableRelations.stream().map(SearchConditionTableRelation::getConditionId).collect(Collectors.toList());
//				List<SearchCondition> entitiesByIds = searchConditionMapper.findEntitiesByIds(conditionIds);
//				if(CollectionUtils.isNotEmpty(entitiesByIds)) {
//					for (SearchCondition condition : entitiesByIds) {
//						vos.add(convertToListItemVo(condition));
//					}
//				}
//			}
//
//			return aopResult.changeSucc(vos);
//		} catch (Exception e) {
//			logger.error(String.format("根据逻辑表(%s)查询条件失败", logicTableId), e);
//			return aopResult.changeErr("根据逻辑表查询关联的查询条件失败");
//		}
//
//	}

//	private SearchConditionDetailVO convertToDetailVo(SearchCondition entity) {
//		SearchConditionDetailVO vo = new SearchConditionDetailVO();
//		vo.setId(entity.getId());
//		vo.setDic(entity.getDic());
//		vo.setName(entity.getName());
//		vo.setDescription(entity.getDescription());
//		vo.setConditionScfServiceName(entity.getConditionScfServiceName());
//		vo.setConditionScfServiceUrl(entity.getConditionScfServiceUrl());
//		vo.setAsyncBoost(entity.getAsyncBoost() == DBConstants.DATA_TRUE);
//		vo.setIgnoreValues(entity.getIgnoreValues());
//		// 开始读取关联的逻辑
//		try {
//			List<SearchConditionTableRelation> tableRelations = searchConditionTableRelationMapper.selectByConditionId(entity.getId());
//			List<LogicTableVO> vos = Lists.newArrayList();
//			vo.setLogicTables(vos);
//			List<Long> tableIds = tableRelations.stream().map(SearchConditionTableRelation::getLogicTableId).collect(Collectors.toList());
//			if(CollectionUtils.isNotEmpty(tableIds)) {
//				List<EntityLogicTable> logicTables = entityLogicTableMapper.findEntitiesByIds(tableIds);
//				for (EntityLogicTable entityTable : logicTables) {
//					LogicTableVO logicTableVO = new LogicTableVO();
//					logicTableVO.setLogicTableId(entityTable.getId());
//					logicTableVO.setLogicTableName(entityTable.getName());
//					vos.add(logicTableVO);
//				}
//			}
//		} catch (Exception e) {
//			logger.error("逻辑表关联的真实表获取失败", e);
//		}
//		return vo;
//	}
}
